package com.zyn.qianwen.user.service.impl;


import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zyn.qianwen.user.dao.TbLogDao;
import com.zyn.qianwen.user.dao.TbLoginDao;
import com.zyn.qianwen.user.entity.Result;
import com.zyn.qianwen.user.entity.TbLog;
import com.zyn.qianwen.user.entity.TbLogin;
import com.zyn.qianwen.user.service.UserService;
import com.zyn.qianwen.user.util.HttpContextUtil;
import com.zyn.qianwen.user.util.HttpGetIp;
import com.zyn.qianwen.user.util.JwtUtil;
import com.zyn.qianwen.user.util.SendCodeUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    TbLoginDao tbLoginDao;

    @Autowired
    TbLogDao tbLogDao;

    @Autowired
    StringRedisTemplate redis;

    @Autowired
    BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    public Result login(TbLogin tbLogin) {
        //获取用户ip地址
        HttpServletRequest requests = HttpContextUtil.getHttpServletRequest();
        String ipAddr = HttpGetIp.getIpAddr(requests);
        if (redis.opsForValue().get(ipAddr) == null) {
            redis.opsForValue().set(ipAddr, "0");
        }
        redis.opsForValue().increment(ipAddr);
        String s1 = redis.opsForValue().get(ipAddr);
        Long expire = redis.getExpire(ipAddr);
        if (expire > 0) {
            return Result.faled(304, "登录次数过多,请稍后重试");
        }
        if (s1.equals("5")) {
            redis.expire(ipAddr, 5, TimeUnit.MINUTES);
            return Result.faled(303, "登录次数过多,请5分钟后重试");
        }
        Date date = new Date();
        QueryWrapper<TbLogin> query = new QueryWrapper<>();
        //判断用户名是否为空
        if (!StringUtils.isEmpty(tbLogin.getLoginName())) {
            query.lambda().eq(TbLogin::getLoginName, tbLogin.getLoginName());
        }
        if (!StringUtils.isEmpty(tbLogin.getPhone())) {
            query.lambda().eq(TbLogin::getPhone, tbLogin.getPhone());
        }
        //查询对象
        TbLogin one = tbLoginDao.selectOne(query);
        if (one != null) {
            //密码是否正确
            if (bCryptPasswordEncoder.matches(tbLogin.getPassword(), one.getPassword())) {
                String token = getToken(one.getId() + "", one.getLoginName(), "", one.getId());
                one.setAccessToken(token);
                Map<String, Object> dataMap = new HashMap<String, Object>();
                dataMap.put("accessToken", token);
                redis.delete("gene_token" + one.getId());
                redis.delete(ipAddr);
                redis.opsForValue().set("gene_token" + one.getId(), token, 5, TimeUnit.HOURS);
                TbLog logEntity = new TbLog();
                String desc = "进行了登录";
                logEntity.setLogText(desc);
                logEntity.setLogName("登录");
                logEntity.setLoginId(one.getId() + "");
                //正确返回登录成功
                tbLogDao.insert(logEntity);
                log.info("登录 登录信息:{},登录时间:{},添加日志:{}", one, date, logEntity);
//                    String encode = Base64.encode(JSON.toJSONString(dataMap));
                return Result.SUCCESS(dataMap);
            } else {
                log.info("登录信息错误 密码错误 登录的信息:{},访问时间:{}", one, date);
                return Result.faled(302, "用户名或密码错误");
            }
        } else {
            redis.opsForValue().get(ipAddr);
            log.info("登录信息错误 用户不存在 登录的信息:{},访问时间:{}", one, date);
            return Result.faled(301, "用户名或密码错误");
        }
    }

    @Override
    public Result register(TbLogin tbLogin) {
        String code = redis.opsForValue().get(tbLogin.getPhone());
        if (!tbLogin.getPhone().equals(code)) {
            log.info("注册失败 验证码错误 注册的邮件:{}", tbLogin.getPhone());
            return Result.faled(300, "验证码错误");
        }
        //查询用户是否存在
        QueryWrapper<TbLogin> query =new QueryWrapper<>();
        query.lambda().eq(TbLogin::getPhone,tbLogin.getPhone());
        TbLogin one = tbLoginDao.selectOne(query);
        if (one!=null){
            log.info("注册失败 手机号已存在 存在的用户:{}",one);
            return  Result.faled(301,"手机号已存在");
        }

        //进行加密 密码
        tbLogin.setPassword(bCryptPasswordEncoder.encode(""));
//        //用户名
        tbLogin.setLoginName(tbLogin.getLoginName());
//        //邮箱
        tbLogin.setPhone(tbLogin.getPhone());

        tbLoginDao.insert(tbLogin);
        //添加数据
        TbLog logEntity=new TbLog();
        String desc="进行了注册";
        logEntity.setLogText(desc);
        logEntity.setLogName("注册");
        logEntity.setLoginId(logEntity.getLoginId());
        tbLogDao.insert(logEntity);
        log.info("注册成功 注册的用户:{},添加的日志信息:{}",tbLogin,logEntity);
        return Result.SUCCESS();
    }

    @Override
    public Result userInfo(HttpServletRequest request){
        String accessToken = null;
         try {
            accessToken= request.getHeaders("accessToken").nextElement();
        }catch (Exception e){
            return Result.faled(400401,"重新登陆");
        };
            if (StringUtils.isEmpty(accessToken)){
            return Result.faled(400402,"登录超时");
        }
        Claims claims = null;
            try {
            claims=claims(accessToken);
        }catch (Exception e){
            return Result.faled(400401,"重新登陆");
        }
        String id = claims.getId();
        String s = redis.opsForValue().get("gene_token" + id);
            if (StringUtils.isEmpty(s)){
            return Result.faled(400401,"重新登陆");
        }
        TbLogin tbLogin = tbLoginDao.selectById(id);
        Map<String,Object> dataMap = new HashMap<String,Object>();
        dataMap.put("username",tbLogin.getLoginName());
        log.info("展示用户信息 展示的用户信息:{}",tbLogin);
        return Result.SUCCESS(dataMap);
    }

    @Override
    public Result logout(HttpServletRequest request) {
        String accessToken = null;
        try {
            accessToken= request.getHeaders("accessToken").nextElement();
        }catch (Exception e){
            return Result.faled(400401,"重新登陆");
        };
        if (StringUtils.isEmpty(accessToken)){
            return Result.faled(400,"登录超时");
        }
        Claims claims = null;
        try {
            claims=claims(accessToken);
        }catch (Exception e){
            return Result.SUCCESS();
        }
        int id = Integer.parseInt(claims.getId());
        TbLog tbLog=new TbLog();
        String desc=id+"退出登录";
        tbLog.setLogName("退出登录");
        tbLog.setLogText(desc);
        tbLog.setLoginId(id+"");
        tbLogDao.insert(tbLog);
        //清除redis中的token
        String token="gene_token"+id;
        Boolean tokens = redis.delete(token);
        if (tokens){
            log.info("{}退出成功",id);
            return Result.SUCCESS();
        }else {
            log.info("退出失败 ");
            return Result.SUCCESS();
        }
    }

    @Override
    public Result sendCode(HttpServletRequest request, TbLogin tbLogin) throws Exception {
        String code = RandomUtil.randomNumbers(6);
        redis.opsForValue().set(tbLogin.getPhone(),code,5, TimeUnit.MINUTES);
        SendCodeUtil.sendMsg(tbLogin.getPhone(),code);

        return null;
    }

    public String getToken(String userid,String username, String roles,Object object){
        //生成tokens
        JwtUtil jwtUtil = new JwtUtil();
        String token = jwtUtil.createJWT(userid,username,roles);
        return token;
    }

    public Claims claims(String accessToken){
        JwtUtil jwtUtil = new JwtUtil();
        Claims claims = jwtUtil.parseJWT(accessToken);
        return claims;
    }
}
